home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK v1.3f3 / Examples / MouseModule / HIDEmulation.c next >
Encoding:
C/C++ Source or Header  |  1999-07-26  |  11.6 KB  |  362 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        HIDEmulation.c
  3.  
  4.     Contains:    HID Emulation glue code between the ADB SHIM and the USB Mouse HID Module
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <DriverServices.h>
  15. #include <CursorDevices.h>
  16. #include <USB.h>
  17. #include <MixedMode.h>
  18.  
  19. // lowmem inline code to access the jADBProc value
  20. #define LMGetJADBProc() (*((volatile UniversalProcPtr *)0x06B8))
  21. #define LMSetJADBProc(value) ((*(UniversalProcPtr *)0x06B8) = (value))
  22.  
  23.  
  24. #include "MouseModule.h"
  25.  
  26. enum
  27.     {
  28.     uppJADBProcProcInfo = kRegisterBased
  29.         | RESULT_SIZE(SIZE_CODE(sizeof(unsigned long)))
  30.         | REGISTER_RESULT_LOCATION(kRegisterD0)
  31.         | REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(unsigned long)))
  32.     };
  33.  
  34. //    an icky little struct that makes the world go around
  35.  
  36. #pragma options align=mac68k
  37.  
  38. typedef    struct    JADBProcGlueCode
  39.     {
  40.     UInt16                    jsrLong;
  41.     UniversalProcPtr        ourJADBProc;
  42.     UInt16                    jmpLong;
  43.     UniversalProcPtr        oldJADBProc;
  44.  
  45.     // We want to flush the DR cache after we modify the above fields.  However,
  46.     // there does not seem to be any way to do this from PPC code.  The only
  47.     // real way to do this, is to copy this data structure onto itself.  BlockMove
  48.     // will flush the DR cache then.  Of course, BlockMove will not flush the DR cache
  49.     // for BlockMove's of less than 20 bytes.  We need to pad our data structure out to be
  50.     // > 20 bytes.
  51.  
  52.     UInt32                    padForBlockMove[5];
  53.     }    JADBProcGlueCode;
  54.  
  55. #pragma options align=reset
  56.  
  57. static JADBProcGlueCode*        gMouseJumpIsland;
  58.  
  59. static UInt32 myMouseADBProc(UInt32 adbReInitState);
  60.  
  61. RoutineDescriptor myMouseADBProcRD = BUILD_ROUTINE_DESCRIPTOR(uppJADBProcProcInfo, (ProcPtr) myMouseADBProc);
  62.  
  63. extern    usbMousePBStruct myMousePB;
  64.  
  65. USBHIDRev2DispatchTable TheHIDModuleDispatchTable =
  66. {
  67.     (UInt32)0,
  68.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  69.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  70.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  71.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  72.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  73.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  74.     (USBHIDInstallNotificationProcPtr)USBHIDInstallNotification
  75. };
  76.  
  77. void USBMouseIn(UInt32 refcon, void * theData)
  78. {
  79. #pragma unused (refcon)
  80.  
  81. USBHIDDataPtr    pMouseData;
  82. static UInt16     oldbuttons = 0;
  83. UInt16     changedbuttons = 0;
  84.  
  85. //    DebugStr("\pIn USBMouseIn");
  86.     pMouseData = (USBHIDDataPtr)theData;
  87.     
  88.     if (myMousePB.pCursorDeviceInfo)        // don't call cursor device manager functions without a good cursor device
  89.     {
  90.         // Tell the Cursor Device Manager that we moved
  91.         if ((pMouseData->mouse.XDelta != 0) || (pMouseData->mouse.YDelta !=0))
  92.         {
  93.             CursorDeviceMove(myMousePB.pCursorDeviceInfo, pMouseData->mouse.XDelta, pMouseData->mouse.YDelta);
  94.         }
  95.         
  96.         // Update with the state of the buttons.
  97.         pMouseData->mouse.buttons &= 0x07;
  98.         changedbuttons = oldbuttons ^ pMouseData->mouse.buttons;
  99.         if (changedbuttons)
  100.         {
  101.             CursorDeviceButtons(myMousePB.pCursorDeviceInfo, (short)pMouseData->mouse.buttons);
  102.         }
  103.         oldbuttons = pMouseData->mouse.buttons;
  104.     }
  105. }
  106.  
  107. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
  108. {
  109.     USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Set interrupt pointer", (UInt32)HIDInterruptFunction);
  110.     myMousePB.interruptRefcon = refcon;            
  111.     
  112.     if (HIDInterruptFunction == USBMouseIn)                // if someone is re-installing the USBMouseIn routine then this is
  113.     {                                                    // an indication that someone earlier requested the interrupt
  114.         myMousePB.pSHIMInterruptRoutine = nil;            // pointer, saved it, and restored it.  When the USBMouseIn
  115.         USBHIDControlDevice(kHIDEnableDemoMode, 0);        // routine is to be used, we've got to re-enable demo mode,
  116.                                                         // otherwise there won't be a cursor device manager entry for us...
  117.     }
  118.     else
  119.     {
  120.         USBHIDControlDevice(kHIDDisableDemoMode, 0);    // disable demo mode
  121.         myMousePB.pSHIMInterruptRoutine = HIDInterruptFunction;
  122.     }
  123.     return noErr;
  124. }
  125.  
  126. OSStatus USBHIDInstallNotification(HIDNotificationProcPtr HIDNotification, UInt32 refcon)
  127. {
  128.     USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Set notification proc ptr", (UInt32)HIDNotification);
  129.     myMousePB.notificationRefcon = refcon;            
  130.     
  131.     myMousePB.pNotificationRoutine = HIDNotification;
  132.     return noErr;
  133. }
  134.  
  135. OSStatus USBHIDPollDevice(void)
  136. {
  137.     return kUSBInternalErr;
  138. }
  139.  
  140. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  141. {
  142. #pragma unused (theControlData)
  143.  
  144.     switch (theControlSelector)
  145.     {
  146.         case kHIDRemoveInterruptHandler:
  147.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Removing interrupt handler!!!", myMousePB.interfaceRef);
  148.             myMousePB.interruptRefcon = nil;
  149.             myMousePB.pSavedInterruptRoutine = nil;
  150.             myMousePB.pSHIMInterruptRoutine = nil;
  151.             if (myMousePB.pCursorDeviceInfo != 0)
  152.             {
  153.                 CursorDeviceDisposeDevice(myMousePB.pCursorDeviceInfo);
  154.                 myMousePB.pCursorDeviceInfo = 0;
  155.             }
  156.             break;
  157.             
  158.         case kHIDRemoveNotification:
  159.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Removing notification!!!", myMousePB.interfaceRef);
  160.             myMousePB.notificationRefcon = nil;
  161.             myMousePB.pNotificationRoutine = NotifyRegisteredHIDUser;
  162.             break;
  163.             
  164.         case kHIDEnableDemoMode:
  165.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Demo Mode Enabled", myMousePB.interfaceRef);
  166.             
  167.             if (myMousePB.pCursorDeviceInfo == 0)
  168.             {
  169.                 myMousePB.pCursorDeviceInfo = &myMousePB.cursorDeviceInfo;
  170.                 CursorDeviceNewDevice(&myMousePB.pCursorDeviceInfo);
  171.                 
  172.                 CursorDeviceSetAcceleration(myMousePB.pCursorDeviceInfo, (Fixed)(1<<16));
  173.                 
  174.                 CursorDeviceSetButtons(myMousePB.pCursorDeviceInfo, 3);            // should actually be set by reading
  175.                                                                                 // the HID descriptor, but lacking
  176.                                                                                 // a parser, we'll just force it
  177.                                                                                 // this way.
  178.                 CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 0, kButtonSingleClick, 0L);
  179.                 CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 1, kButtonSingleClick, 0L);
  180.                 CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 2, kButtonSingleClick, 0L);
  181.                 CursorDeviceUnitsPerInch(myMousePB.pCursorDeviceInfo, (Fixed)(myMousePB.unitsPerInch));
  182.             
  183.                 myMousePB.pSavedInterruptRoutine = myMousePB.pSHIMInterruptRoutine;
  184.                 myMousePB.pSHIMInterruptRoutine = USBMouseIn;
  185.             }
  186.             break;
  187.  
  188.         case kHIDDisableDemoMode:
  189.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Demo Mode Disabled", myMousePB.interfaceRef);
  190.             if (myMousePB.pCursorDeviceInfo != 0)
  191.             {
  192.                 CursorDeviceDisposeDevice(myMousePB.pCursorDeviceInfo);
  193.                 myMousePB.pCursorDeviceInfo = 0;
  194.             }
  195.             myMousePB.pSHIMInterruptRoutine = myMousePB.pSavedInterruptRoutine;
  196.             break;
  197.  
  198.         default:
  199.             return paramErr;
  200.     }
  201.     return noErr;
  202. }
  203.  
  204.  
  205.  
  206. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  207. {
  208. HIDInterruptProcPtr * pHIDIntProcPtr;
  209. UInt32 * pUnits;
  210. UInt32 * pInterruptRefcon;
  211.  
  212.     switch (theInfoSelector)
  213.     {
  214.         case kHIDGetDeviceUnitsPerInch:
  215.             pUnits = (UInt32*)theInfo;
  216.             *pUnits = (UInt32)(myMousePB.unitsPerInch);
  217.             break;
  218.             
  219.         case kHIDGetInterruptHandler:
  220.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Get interrupt pointer", (UInt32)(myMousePB.pSHIMInterruptRoutine));
  221.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;     
  222.             *pHIDIntProcPtr = myMousePB.pSHIMInterruptRoutine;
  223.             break;
  224.  
  225.         case kHIDGetInterruptRefcon:
  226.             pInterruptRefcon = (UInt32 *)theInfo;
  227.             *pInterruptRefcon = myMousePB.interruptRefcon;
  228.             break;
  229.         
  230.         default:
  231.             return paramErr;
  232.     }
  233.     return noErr;
  234. }
  235.  
  236. OSStatus USBHIDEnterPolledMode(void)
  237. {
  238.     return unimpErr;
  239. }
  240.  
  241. OSStatus USBHIDExitPolledMode(void)
  242. {
  243.     return unimpErr;
  244. }
  245.  
  246. void NotifyRegisteredHIDUser(UInt32 refcon, UInt32 reportSize, void * theReport, USBReference theInterfaceRef)
  247. //void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  248. {
  249. #pragma unused (refcon)
  250. #pragma unused (reportSize)
  251. #pragma unused (theInterfaceRef)
  252.  
  253. USBHIDData        theMouseData;
  254. SInt8            myXDelta, myYDelta;
  255. char *             hidReport;
  256.  
  257.     hidReport = (char *)theReport;
  258.     theMouseData.mouse.buttons = (UInt16)hidReport[0];
  259.     
  260.     myXDelta = (SInt8)hidReport[1];
  261.     myYDelta = (SInt8)hidReport[2];  
  262.     
  263.     theMouseData.mouse.XDelta = (SInt16)myXDelta;
  264.     theMouseData.mouse.YDelta = (SInt16)myYDelta;
  265.     if (myMousePB.pSHIMInterruptRoutine)
  266.     {
  267.         (*myMousePB.pSHIMInterruptRoutine)(myMousePB.interruptRefcon, (void *)&theMouseData);
  268.     }
  269. }
  270.  
  271. static UInt32
  272. myMouseADBProc(UInt32 adbReInitState)
  273. {
  274.  
  275.     // adbReInitState = 0, just before the cursor device manager devices are removed.
  276.     // adbReInitState = non-zero, after the devices are removed.  This is when we need to
  277.     // reinsert our device.
  278.  
  279.     if (adbReInitState == 0)
  280.     {
  281.         if (myMousePB.pCursorDeviceInfo != 0)                
  282.         {
  283.             myMousePB.pCursorDeviceInfo = 0;
  284.         }
  285.     }
  286.     else
  287.     {
  288.         if (myMousePB.pSHIMInterruptRoutine == USBMouseIn)  // are we using our cursor device?
  289.         {
  290.             myMousePB.pCursorDeviceInfo = &myMousePB.cursorDeviceInfo;
  291.             CursorDeviceNewDevice(&myMousePB.pCursorDeviceInfo);
  292.             
  293.             CursorDeviceSetAcceleration(myMousePB.pCursorDeviceInfo, (Fixed)(1<<16));
  294.             
  295.             CursorDeviceSetButtons(myMousePB.pCursorDeviceInfo, 3);            // should actually be set by reading
  296.                                                                             // the HID descriptor, but lacking
  297.                                                                             // a parser, we'll just force it
  298.                                                                             // this way.
  299.             CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 0, kButtonSingleClick, 0L);
  300.             CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 1, kButtonSingleClick, 0L);
  301.             CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 2, kButtonSingleClick, 0L);
  302.             CursorDeviceUnitsPerInch(myMousePB.pCursorDeviceInfo, (Fixed)(myMousePB.unitsPerInch));
  303.         }
  304.     }
  305.  
  306.     return(adbReInitState);
  307. }
  308.  
  309.  
  310. void ChainJADBProc(void)
  311. {
  312.     JADBProcGlueCode            stackedBasedVersion;
  313.  
  314.     // Hook ourselves into JADBProc to be notified whenever ADBReInit gets called.  As a
  315.     // result of ADBReInit(), any CursorDevice records are deleted.  So, we'll hook ourselves
  316.     // into JADBProc, and recreate our CursorDevice record whenever ADBReInit has completed.
  317.  
  318.  
  319.     if ((gMouseJumpIsland = (JADBProcGlueCode *) NewPtrSysClear(sizeof(JADBProcGlueCode))) == nil)
  320.     {
  321.         return;  // just bail if we can't allocate any memory
  322.     }
  323.  
  324.     stackedBasedVersion.jsrLong = 0x4EB9;
  325.     stackedBasedVersion.ourJADBProc = &myMouseADBProcRD;
  326.     stackedBasedVersion.jmpLong = 0x4EF9;
  327.     stackedBasedVersion.oldJADBProc = LMGetJADBProc();
  328.  
  329.     // We want to flush the DR cache after we modify the above fields.  However,
  330.     // there does not seem to be any way to do this from PPC code.  The only
  331.     // real way to do this, is to copy this data structure onto itself.  BlockMove
  332.     // will flush the DR cache then.  Of course, BlockMove will not flush the DR cache
  333.     // for BlockMove's of less than 20 bytes.  We need to pad our data structure out to be
  334.     // > 20 bytes.
  335.  
  336.     BlockMove(&stackedBasedVersion, gMouseJumpIsland, sizeof(JADBProcGlueCode));
  337.  
  338.     LMSetJADBProc((UniversalProcPtr) gMouseJumpIsland);
  339. }
  340.  
  341. void UnchainJADBProc(void)
  342. {
  343.     JADBProcGlueCode        stackedBasedVersion;
  344.  
  345.     // We cannot totally remove ourselves from the ADBReinit chain.  Since someone might have patched
  346.     // themselves into the JADBProc chain after us, we need to leave a small jump island pointing
  347.     // to the person before us in the chain.
  348.  
  349.     // We want to flush the DR cache after we modify the above fields.  However,
  350.     // there does not seem to be any way to do this from PPC code.  The only
  351.     // real way to do this, is to copy this data structure onto itself.  BlockMove
  352.     // will flush the DR cache then.  Of course, BlockMove will not flush the DR cache
  353.     // for BlockMove's of less than 20 bytes.  We need to pad our data structure out to be
  354.     // > 20 bytes.
  355.  
  356.     BlockMove(gMouseJumpIsland, &stackedBasedVersion, sizeof(JADBProcGlueCode));
  357.  
  358.     stackedBasedVersion.jsrLong = 0x2048;
  359.     stackedBasedVersion.ourJADBProc = (UniversalProcPtr) 0x20482048;
  360.  
  361.     BlockMove(&stackedBasedVersion, gMouseJumpIsland, sizeof(JADBProcGlueCode));
  362. }